/**
 * Copyright (c) 2008, Andrew Carter
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, are 
 * permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of 
 * conditions and the following disclaimer. Redistributions in binary form must reproduce 
 * the above copyright notice, this list of conditions and the following disclaimer in 
 * the documentation and/or other materials provided with the distribution. Neither the 
 * name of Andrew Carter nor the names of contributors may be used to endorse or promote 
 * products derived from this software without specific prior written permission. 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
 * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.acarter.scenemonitor.propertydescriptor.editor;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import com.jme.math.Quaternion;
import com.jme.math.Vector3f;

/**
 * 
 * @author Andrew Carter
 */
public class QuaternionEditorPanel extends A_EditorPanel {

	/**	 */
	private static final long serialVersionUID = 1L;
	
	/**  */
	private JDialog dialog = null;
	
	/**  */
	private Quaternion quat;
	
	/**  */
	private Quaternion qTemp;
	
	/**  */
	private Quaternion qRestore;

	/**  */
	private JTextField rotXfield;

	/**  */
	private JTextField rotYfield;

	/**  */
	private JTextField rotZfield;

	/**  */
	private JButton xSlider;

	/**  */
	private JButton ySlider;

	/**  */
	private JButton zSlider;
	
	/**  */
	private JButton cancel;
	
	/**  */
	private JButton done;
	
	/**  */
	private int width = -1;

	/**
	 * 
	 * @param label 
	 * @param quat 
	 * @param state
	 */
	public QuaternionEditorPanel(JDialog dialog, Quaternion quat) {

		this.dialog = dialog;
		this.quat = quat;

		qTemp = new Quaternion();
		qRestore = new Quaternion(quat);
		
		build();
		initValues();
	}

	/**
	 * 
	 * @param label 
	 * @param quat 
	 * @param width 
	 * @param state
	 */
	public QuaternionEditorPanel(JDialog dialog, Quaternion quat, int width) {

		this.dialog = dialog;
		this.quat = quat;
		this.width = width;

		qTemp = new Quaternion();
		
		build();
		initValues();
	}

	/**
	 * 
	 * @param label 
	 * @param quat 
	 * @param width 
	 * @param state
	 */
	public QuaternionEditorPanel(JDialog dialog, Quaternion quat, int width, int fieldWidth) {

		this.dialog = dialog;
		this.quat = quat;
		this.width = width;
		fieldDim.setSize(fieldWidth, fieldDim.getHeight());

		qTemp = new Quaternion();
		
		build();
		initValues();
	}

	/**
	 * 
	 *
	 */
	private void build() {
		
		JLabel rotX = new JLabel("X: ");
		rotX.setFont(font);
		JLabel rotY = new JLabel("Y: ");
		rotY.setFont(font);
		JLabel rotZ = new JLabel("Z: ");
		rotZ.setFont(font);

		rotXfield = new JTextField();
		rotXfield.setFont(font);
		rotXfield.setPreferredSize(fieldDim);
		rotXfield.setMaximumSize(rotXfield.getPreferredSize());
		rotXfield.setEnabled(false);

		xSlider = new JButton();
		xSlider.setPreferredSize(sliderDim);
		xSlider.setMaximumSize(xSlider.getPreferredSize());
		xSlider.setToolTipText(sliderTooltip);

		rotYfield = new JTextField();
		rotYfield.setFont(font);
		rotYfield.setPreferredSize(fieldDim);
		rotYfield.setMaximumSize(rotYfield.getPreferredSize());
		rotYfield.setEnabled(false);

		ySlider = new JButton();
		ySlider.setPreferredSize(sliderDim);
		ySlider.setMaximumSize(ySlider.getPreferredSize());
		ySlider.setToolTipText(sliderTooltip);

		rotZfield = new JTextField();
		rotZfield.setFont(font);
		rotZfield.setPreferredSize(fieldDim);
		rotZfield.setMaximumSize(rotZfield.getPreferredSize());
		rotZfield.setEnabled(false);

		zSlider = new JButton();
		zSlider.setPreferredSize(sliderDim);
		zSlider.setMaximumSize(zSlider.getPreferredSize());
		zSlider.setToolTipText(sliderTooltip);

		done = new JButton("Done");
		done.setFont(font);
		done.setPreferredSize(new Dimension(42, 15));
		done.setMaximumSize(done.getPreferredSize());
		done.setMargin(insets);

		cancel = new JButton("Cancel");
		cancel.setFont(font);
		cancel.setPreferredSize(new Dimension(42, 15));
		cancel.setMaximumSize(cancel.getPreferredSize());
		cancel.setMargin(insets);

		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
		buttonPanel.add(done);
		buttonPanel.add(Box.createRigidArea(new Dimension(5, 0)));
		buttonPanel.add(cancel);
		buttonPanel.add(Box.createRigidArea(new Dimension(1, 0)));

		JPanel buttonPanel2 = new JPanel();
		buttonPanel2.setLayout(new BoxLayout(buttonPanel2, BoxLayout.Y_AXIS));
		buttonPanel2.add(Box.createGlue());
		buttonPanel2.add(buttonPanel);
		buttonPanel2.add(Box.createGlue());
		
		setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
		
		if(width != -1){
			add(Box.createRigidArea(new Dimension(width, 0)));
		}
		else {
			add(Box.createRigidArea(new Dimension(1, 0)));
			add(Box.createGlue());
		}

		add(rotX);
		add(rotXfield);
		add(xSlider);
		add(Box.createRigidArea(new Dimension(5, 0)));
		add(rotY);
		add(rotYfield);
		add(ySlider);
		add(Box.createRigidArea(new Dimension(5, 0)));
		add(rotZ);
		add(rotZfield);
		add(zSlider);
		add(Box.createRigidArea(new Dimension(5, 0)));
		add(buttonPanel2);

		if(width != -1)
			add(Box.createGlue());
		
		// listeners
		xSlider.addMouseMotionListener(new MouseMotionListener() {

			public void mouseDragged(MouseEvent e) {
				
				float val  = slideValue(e, 0, 1);

				onRotationUpdate(val, Vector3f.UNIT_X);
				
				if(callback != null)
					callback.componentModifiedCallback();
			}

			public void mouseMoved(MouseEvent e) {
			}
		});
		
		ySlider.addMouseMotionListener(new MouseMotionListener() {

			public void mouseDragged(MouseEvent e) {
				
				float val  = slideValue(e, 0, 1);

				onRotationUpdate(val, Vector3f.UNIT_Y);
				
				if(callback != null)
					callback.componentModifiedCallback();
			}

			public void mouseMoved(MouseEvent e) {
			}
		});
		
		zSlider.addMouseMotionListener(new MouseMotionListener() {

			public void mouseDragged(MouseEvent e) {
				
				float val  = slideValue(e, 0, 1);

				onRotationUpdate(val, Vector3f.UNIT_Z);
				
				if(callback != null)
					callback.componentModifiedCallback();
			}

			public void mouseMoved(MouseEvent e) {
			}
		});

		done.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent evt) {

				dialog.setVisible(false);
			}
		});

		cancel.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent evt) {

				restoreValue();

				dialog.setVisible(false);
			}
		});
	}

	/**
	 * 
	 * 
	 */
	public void initValues() {

		rotXfield.setText(Float.toString(quat.x));
		rotYfield.setText(Float.toString(quat.y));
		rotZfield.setText(Float.toString(quat.z));
	}
	
	/**
	 * 
	 */
	public void restoreValue() {
		
		quat.set(qRestore);
		
		if(callback != null)
			callback.componentModifiedCallback();
	}
	
	/**
	 * @param delta 
	 * @param axis 
	 * 
	 *
	 */
	public void onRotationUpdate(float delta, Vector3f axis) {

		qTemp.fromAngleNormalAxis(delta, axis);
		quat.multLocal(qTemp);
		quat.normalize();
		
		initValues();
	}
	
	@Override
	public void setEnabled(boolean enabled)
	{
		super.setEnabled(enabled);
		
		rotXfield.setEnabled(enabled);
		rotYfield.setEnabled(enabled);
		rotZfield.setEnabled(enabled);
		xSlider.setEnabled(enabled);
		ySlider.setEnabled(enabled);
		zSlider.setEnabled(enabled);
		cancel.setEnabled(enabled);
	}
}
